import os
import json
import datetime
import requests


class WorkdayChecker:
    """
    工作日检查器，用于判断一个日期是否为工作日
    规则：
    1. 正常情况下，周一至周五是工作日，周六日是休息日
    2. 法定节假日（如元旦、春节等）是休息日
    3. 调休日（如节假日前后的周末调休）是工作日
    """
    
    def __init__(self, cache_dir=None):
        """
        初始化工作日检查器
        
        Args:
            cache_dir: 缓存目录，默认为当前文件所在目录
        """
        if cache_dir is None:
            # 获取当前文件所在目录作为缓存目录
            self.cache_dir = os.path.dirname(os.path.abspath(__file__))
        else:
            self.cache_dir = cache_dir
            
        # 确保缓存目录存在
        os.makedirs(self.cache_dir, exist_ok=True)
        
        # 节假日数据缓存
        self.holiday_cache = {}
    
    def _get_cache_file_path(self, year):
        """
        获取指定年份的节假日数据缓存文件路径
        
        Args:
            year: 年份
            
        Returns:
            缓存文件路径
        """
        return os.path.join(self.cache_dir, f"holiday_data_{year}.json")
    
    def _load_holiday_data_from_cache(self, year):
        """
        从缓存加载节假日数据
        
        Args:
            year: 年份
            
        Returns:
            节假日数据字典，如果缓存不存在则返回None
        """
        cache_file = self._get_cache_file_path(year)
        if os.path.exists(cache_file):
            try:
                with open(cache_file, 'r', encoding='utf-8') as f:
                    return json.load(f)
            except Exception as e:
                print(f"加载缓存数据出错: {e}")
        return None
    
    def _save_holiday_data_to_cache(self, year, data):
        """
        保存节假日数据到缓存
        
        Args:
            year: 年份
            data: 节假日数据
        """
        cache_file = self._get_cache_file_path(year)
        try:
            with open(cache_file, 'w', encoding='utf-8') as f:
                json.dump(data, f, ensure_ascii=False, indent=2)
        except Exception as e:
            print(f"保存缓存数据出错: {e}")
    
    def _fetch_holiday_data(self, year):
        """
        从API获取节假日数据
        
        Args:
            year: 年份
            
        Returns:
            节假日数据字典
        """
        url = f"https://timor.tech/api/holiday/year/{year}"
        headers = {
            'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36'
        }
        try:
            response = requests.get(url, headers=headers, timeout=10)
            response.raise_for_status()
            return response.json()
        except Exception as e:
            print(f"获取节假日数据出错: {e}")
            return None
    
    def get_holiday_data(self, year):
        """
        获取指定年份的节假日数据，优先从缓存获取，如果缓存不存在则从API获取
        
        Args:
            year: 年份
            
        Returns:
            节假日数据字典
        """
        # 转换为字符串类型的年份
        year = str(year)
        
        # 如果已经在内存缓存中，直接返回
        if year in self.holiday_cache:
            return self.holiday_cache[year]
        
        # 尝试从文件缓存加载
        data = self._load_holiday_data_from_cache(year)
        if data is not None:
            # 保存到内存缓存
            self.holiday_cache[year] = data
            return data
        
        # 从API获取数据
        data = self._fetch_holiday_data(year)
        if data is not None and data.get('code') == 0:
            # 保存到缓存
            self._save_holiday_data_to_cache(year, data)
            # 保存到内存缓存
            self.holiday_cache[year] = data
            return data
        
        # 如果获取失败，返回空字典
        return {"code": -1, "holiday": {}}
    
    def is_workday(self, date_obj): # Changed to accept date_obj directly
        """
        判断指定日期是否为工作日
        
        Args:
            date_obj: 日期对象(datetime.date)
            
        Returns:
            True: 是工作日
            False: 不是工作日
        """
        if not isinstance(date_obj, datetime.date):
            raise TypeError("date_obj参数必须是datetime.date对象")
        
        # 获取年份和月日
        year = date_obj.year
        month_day_str = date_obj.strftime("%m-%d") # API uses MM-DD
        
        # 获取节假日数据
        holiday_data = self.get_holiday_data(year)
        
        # 如果获取失败，按照常规规则判断（周一至周五为工作日）
        if holiday_data.get('code') != 0:
            return date_obj.weekday() < 5  # 0-4为周一至周五
        
        # 获取当天的节假日信息
        # API data: "holiday": {"01-01": {"holiday": true, "name": "元旦", "wage": 3, "date": "2025-01-01", "rest": 1}}
        #           {"01-26": {"holiday": false, "name": "春节前补班", "wage": 1, "date": "2025-01-26", "rest": 1}}
        day_info = holiday_data.get('holiday', {}).get(month_day_str)
        
        if day_info:
            # holiday为True表示是法定节假日(休息日)，为False表示是调休工作日
            return not day_info.get('holiday', False) 
        else:
            # 如果没有特殊安排，按照常规规则判断（周一至周五为工作日）
            return date_obj.weekday() < 5  # 0-4为周一至周五

# Example usage (for testing workday_checker itself)
def _test_workday_checker():
    checker = WorkdayChecker()
    test_dates_objs = [
        datetime.date(2025, 1, 1),  # 元旦，休息日
        datetime.date(2025, 1, 26), # 春节前补班，工作日 (API: holiday=false)
        datetime.date(2025, 1, 28), # 除夕，休息日 (API: holiday=true)
        datetime.date(2025, 1, 4), # 周六，假设是春节前补班 (API会说明)
        datetime.date(2024, 10, 12), # 2024年国庆后补班周六，工作日 (API: holiday=false)
        datetime.date(2024, 10, 6), # 2024年国庆期间周日，休息日 (API: holiday=true)
        datetime.date(2024, 7, 20), # 普通周六, 休息日
        datetime.date(2024, 7, 22), # 普通周一, 工作日
    ]
    for date_obj_to_test in test_dates_objs:
        is_work = checker.is_workday(date_obj_to_test)
        print(f"{date_obj_to_test.strftime('%Y-%m-%d')} 是{'工作日' if is_work else '休息日'}")

if __name__ == "__main__":
    # _test_workday_checker() # Uncomment to test workday_checker independently
    pass
